#include <iostream>
#include <fstream>
#include <cctype>

#include "token.h"

namespace jsearch
{

struct token::Impl
{
	public:
		Impl(const std::string& file);
		~Impl();

		std::string next_token();

	private:
		void filter(std::string &s);

	private:
		std::string file;
		std::ifstream in;
};



//============================================================
//  implements
//============================================================
token::Impl::Impl(const std::string& file_)
:file(file_)
{

	if (file_.empty()) {
		std::cerr<<"error:file name should not be empty string"
			<<std::endl;

		exit(1);
	}

	in.open(file_.c_str());
	if (in.bad()) {
		std::cout<<"error:file open error."<<std::endl;
		exit(1);
	}
}

token::Impl::~Impl()
{
	in.clear();
	in.close();
}

std::string token::Impl::next_token()
{
	std::string s;
	char c;

	while (in.get(c)) {
		if (isalpha(c))
			break;
	}

	if (in.eof()) {
		return s;
	} else { 
		s.push_back(c);
	}

	while (in.get(c)){
		if (isalpha(c) || c=='\''||	c=='-' || c=='_' ) {
			s.push_back(c);
		} else { 
			break;
		}
	}

	if (in.bad())
		in.clear();

	filter(s);

	return s;
}

void token::Impl::filter( std::string& s )
{
	std::string::size_type pos=0;
	for (pos=0; pos<s.size(); pos++)
		s.at(pos)=tolower( s.at(pos) );

	while (s.at(s.size()-1) == '\'')
		s.erase(s.size()-1);
}


token::token(std::string file)
	:pimpl( new Impl(file) )
{ }


std::string token::next_token()
{
	return pimpl->next_token();
}

}//end namespace
